<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/vue.global.js"></script>
</head>

<body>
    <div id="app">
        <p>
            {{zhang.name}}----{{zhang.age}}----{{zhang.info.height}}----{{zhang.info.weight}}
        </p>
        <p>
            <button @click="changeName">changeName</button>
            <button @click="changeAge">changeAge</button>
            <button @click="changeHeight">changeHeight</button>
        </p>
    </div>
</body>
<script>

    // 组合式 API 的核心思想是直接在函数作用域内定义响应式状态变量，并将从多个函数中得到的状态组合起来处理复杂问题

    let { createApp } = Vue;
    let { ref, reactive, computed, toRef,toRefs } = Vue;


    let app = createApp({
        setup(props) {

            // ref()  => 创建一个对"值类型"数据的引用,返回一个ref对象 (存 对象类型 也可以, 可以通过.value获取修改对象)
            // 注意:
            // 1. setup函数中对ref对象取值和赋值 依赖于.value属性
            // 2. 代理对象中 / template中 ref对象会被解包 => 直接使用变量即可
            // 3. ref() 也可以存对象类型, 此时Vue响应式对ref数据的数据拦截是深层的(可以检测value值是否改变,也可以检测子对象上属性是否改变 => 触发视图更新)


            // reactive()  创建一个对'对象'数据的引用 返回一个对象的响应式代理。(只能获取修改代理对象的子属性)

            // Vue响应式检测reactive()创建的响应式代理数据时是深层的(可以检测根对象及其子对象的属性改变)

            /* let zhang = reactive({name:"张三",age:18,info:{height:177,weight:70}});
            console.log("zhang",zhang);
            console.log("zhang",zhang.name);
            console.log("zhang",zhang.age);
            console.log("zhang",zhang.info);
            console.log("zhang",zhang.info.height);
            console.log("zhang",zhang.info.weight);


            

            let changeName = ()=>{
                zhang.name = "李四"
            }
            
            let changeAge = ()=>{
                zhang.age ++
            }

            let changeHeight = ()=>{
                zhang.info.height ++
            } */


            let zhang = reactive({ name: "张三", age: 18, info: { height: 177, weight: 70 } });
            console.log("zhang", zhang);
            console.log("zhang", zhang.info);

            // 传统的写法取值和赋值  => 没有问题
            // zhang.name => 对代理对象取值,触发取值拦截
            // zhang.name = xxx =>  对代理对象赋值,触发赋值拦截,视图会更新


            // 解构写法   => 丧失响应性
            // name = zhang.name => 创建一个新的变量,将zhang.name的值取出来(取值拦截)值给新变量
            // name = xxx => 此写法只给变量name赋值,和代理对象zhang没有任何管理, 视图不会更新

            // 直接对代理对象解构, 丧失响应性写法
            // let { name, age, info: { height, weight } } = zhang;

            /* console.log(name, age, height);

            let changeName = () => {
                name = "李四";
            }

            let changeAge = () => {
                age++;
                console.log(age);
            }

            let changeHeight = () => {
                height++;
            } */


            // 优化方法  => 虽然创建了一个新数据,但是我们期望新数据发生改变后,源数据也会跟着改变

            // 此写法:根据 reactive响应式代理 得到新的计算属性(ref对象)   =>  方法很好就是要自己手搓 => 麻烦
            // 对 name  取值依赖于 zhang.name;
            // 对 name  赋值操作  zhang.name;

            // 使用官方的方法
            // toRef()   => 每次只能处理一个
            // 单个处理基于响应式对象上的一个属性，创建一个对应的 ref。这样创建的 ref 与其源属性保持同步：改变源属性的值将更新 ref 的值，反之亦然。 
            // let name = toRef(zhang,"name");
            // let age = toRef(zhang,"age");
            // let height = toRef(zhang.info,"height");


            // toRefs() 
            // 批量处理基于响应式对象上的属性(仅限于根属性), 返回一个新对象,新对象的键名同源对象,键值都是依赖于源对象的ref对象

            // let res = toRefs(zhang);   // {name:ref(),age:ref(),info:ref()}
            // console.log(11111, res);

            let {name,age} = toRefs(zhang);   // {name:ref(),age:ref(),info:ref}
            let {height,weight} = toRefs(zhang.info);   // {height:ref(),weight:ref()}

            console.log(name, age, height);

            let changeName = () => {
                name.value = "李四";
            }

            let changeAge = () => {
                age.value++;
                console.log(age);
            }

            let changeHeight = () => {
                height.value++;
            }

            return {
                zhang,
                changeName,
                changeAge,
                changeHeight,
            }
        },
        mounted() {
            console.log("代理对象,this", this);

            /*  new Proxy({},{
                 get(){
                     // 判断是否是ref对象  => ref.value
                 },
                 set(){
                     // 判断是否是ref对象   => ref.value = xxx
                 }
             }) */
        },
    })


    app.mount("#app");


</script>

</html>